2 MQTT Control Packet format

2.1 Structure of an MQTT Control Packet

The MQTT protocol works by exchanging a series of MQTT Control Packets in a defined way. This section describes the format of these packets.

An MQTT Control Packet consists of up to three parts, always in the following order as illustrated in Figure 2.1 - Structure of an MQTT Control Packet.

Figure 2.1 – Structure of an MQTT Control Packet

Fixed header, present in all MQTT Control Packets

Variable header, present in some MQTT Control Packets

Payload, present in some MQTT Control Packets

2.2 Fixed header

Each MQTT Control Packet contains a fixed header. Figure 2.2 - Fixed header format illustrates the fixed header format.

Figure 2.2 - Fixed header format

Bit

7

6

5

4

3

2

1

0

byte 1

MQTT Control Packet type

Flags specific to each MQTT Control Packet type

byte 2…

Remaining Length

2.2.1 MQTT Control Packet type

Represented as a 4-bit unsigned value, the values are listed in Table 2.1 - Control packet types.

Table 2.1 - Control packet types

Name

Value

Direction of flow

Description

Reserved

0

Forbidden

Reserved

CONNECT

1

Client to Server

Client request to connect to Server

CONNACK

2

Server to Client

Connect acknowledgment

PUBLISH

3

Client to Server

          or

Server to Client

Publish message

PUBACK

4

Client to Server

          or

Server to Client

Publish acknowledgment

PUBREC

5

Client to Server

          or

Server to Client

Publish received (assured delivery part 1)

PUBREL

6

Client to Server

          or

Server to Client

Publish release (assured delivery part 2)

PUBCOMP

7

Client to Server

          or

Server to Client

Publish complete (assured delivery part 3)

SUBSCRIBE

8

Client to Server

Client subscribe request

SUBACK

9

Server to Client

Subscribe acknowledgment

UNSUBSCRIBE

10

Client to Server

Unsubscribe request

UNSUBACK

11

Server to Client

Unsubscribe acknowledgment

PINGREQ

12

Client to Server

PING request

PINGRESP

13

Server to Client

PING response

DISCONNECT

14

Client to Server

Client is disconnecting

Reserved

15

Forbidden

Reserved

2.2 Flags

The remaining bits [3-0] of byte 1 in the fixed header contain flags specific to each MQTT Control Packet type as listed in the Table 2.2 - Flag Bits below. Where a flag bit is marked as “Reserved” in Table 2.2 - Flag Bits, it is reserved for future use and MUST be set to the value listed in that table [MQTT-2.2.2-1]. If invalid flags are received, the receiver MUST close the Network Connection [MQTT-2.2.2-2]. See Section 4.8 Handling errors for details about handling errors.

Table 2.2 - Flag Bits

Control Packet

Fixed header flags

Bit 3

Bit 2

Bit 1

Bit 0

CONNECT

Reserved

0

0

0

0

CONNACK

Reserved

0

0

0

0

PUBLISH

Used in MQTT 3.1.1

DUP1

QoS2

QoS2

RETAIN3

PUBACK

Reserved

0

0

0

0

PUBREC

Reserved

0

0

0

0

PUBREL

Reserved

0

0

1

0

PUBCOMP

Reserved

0

0

0

0

SUBSCRIBE

Reserved

0

0

1

0

SUBACK

Reserved

0

0

0

0

UNSUBSCRIBE

Reserved

0

0

1

0

UNSUBACK

Reserved

0

0

0

0

PINGREQ

Reserved

0

0

0

0

PINGRESP

Reserved

0

0

0

0

DISCONNECT

Reserved

0

0

0

0

 

DUP1  = Duplicate delivery of a PUBLISH Control Packet

QoS2  = PUBLISH Quality of Service

RETAIN3 = PUBLISH Retain flag

See Section 3.3.1 Fixed header for a description of the DUP, QoS, and RETAIN flags in the PUBLISH Control Packet.

2.2.3 Remaining Length

Position: starts at byte 2.

The Remaining Length is the number of bytes remaining within the current packet, including data in the variable header and the payload. The Remaining Length does not include the bytes used to encode the Remaining Length.

The Remaining Length is encoded using a variable length encoding scheme which uses a single byte for values up to 127. Larger values are handled as follows. The least significant seven bits of each byte encode the data, and the most significant bit is used to indicate that there are following bytes in the representation. Thus each byte encodes 128 values and a "continuation bit". The maximum number of bytes in the Remaining Length field is four.

Non normative comment

For example, the number 64 decimal is encoded as a single byte, decimal value 64, hexadecimal 0x40. The number 321 decimal (= 65 + 2*128) is encoded as two bytes, least significant first. The first byte is 65+128 = 193. Note that the top bit is set to indicate at least one following byte. The second byte is 2.

Non normative comment

This allows applications to send Control Packets of size up to 268,435,455 (256 MB). The representation of this number on the wire is: 0xFF, 0xFF, 0xFF, 0x7F.

Solace Implementation Note

Solace has limits to the size of a message, depending on the message QoS and the type of event broker.

Table 2.4 shows the Remaining Length values represented by increasing numbers of bytes.

Table 2.4 Size of Remaining Length field

Digits

From

To

1

0 (0x00)

127 (0x7F)

2

128 (0x80, 0x01)

16 383 (0xFF, 0x7F)

3

16 384 (0x80, 0x80, 0x01)

2 097 151 (0xFF, 0xFF, 0x7F)

4

2 097 152 (0x80, 0x80, 0x80, 0x01)

268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

Non normative comment

The algorithm for encoding a non negative integer (X) into the variable length encoding scheme is as follows:

               do

              encodedByte = X MOD 128

              X = X DIV 128

             // if there are more data to encode, set the top bit of this byte

             if ( X > 0 )

                 encodedByte = encodedByte OR 128

             endif

                 'output' encodedByte

        while ( X> 0 )

 

Where MOD is the modulo operator (% in C), DIV is integer division (/ in C), and OR is bit-wise or (| in C).

Non normative comment

The algorithm for decoding the Remaining Length field is as follows:

       multiplier = 1

       value = 0

       do

            encodedByte = 'next byte from stream'

            value += ( encodedByte AND 127) * multiplier

            multiplier *= 128

            if (multiplier > 128*128*128)

               throw Error(Malformed Remaining Length)

       while (( encodedByte AND 128) != 0)

 

where AND is the bit-wise and operator (& in C).

 

When this algorithm terminates, value contains the Remaining Length value.

2.3 Variable header

Some types of MQTT Control Packets contain a variable header component. It resides between the fixed header and the payload. The content of the variable header varies depending on the Packet type. The Packet Identifier field of variable header is common in several packet types.

2.3.1 Packet Identifier

Figure 2.3 - Packet Identifier bytes

Bit

7

6

5

4

3

2

1

0

byte 1

Packet Identifier MSB

byte 2

Packet Identifier LSB

The variable header component of many of the Control Packet types includes a 2 byte Packet Identifier field. These Control Packets are PUBLISH (where QoS > 0), PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK.

SUBSCRIBE, UNSUBSCRIBE, and PUBLISH (in cases where QoS > 0) Control Packets MUST contain a non-zero 16-bit Packet Id entifier [MQTT-2.3.1-1]. Each time a Client sends a new packet of one of these types it MUST assign it a currently unused Packet Identifier [MQTT-2.3.1-2]. If a Client re-sends a particular Control Packet, then it MUST use the same Packet Identifier in subsequent re-sends of that packet. The Packet Identifier becomes available for reuse after the Client has processed the corresponding acknowledgement packet. In the case of a QoS 1 PUBLISH this is the corresponding PUBACK; in the case of QoS 2 it is PUBCOMP. For SUBSCRIBE or UNSUBSCRIBE it is the corresponding SUBACK or UNSUBACK [MQTT-2.3.1-3]. The same conditions apply to a Server when it sends a PUBLISH with QoS > 0 [MQTT-2.3.1-4].

A PUBLISH Packet MUST NOT contain a Packet Identifier if its QoS value is set to 0 [MQTT-2.3.1-5].

A PUBACK, PUBREC or PUBREL Packet MUST contain the same Packet Identifier as the PUBLISH Packet that was originally sent [MQTT-2.3.1-6]. Similarly SUBACK and UNSUBACK MUST contain the Packet Id entifier that was used in the corresponding SUBSCRIBE and UNSUBSCRIBE Packet respectively [MQTT-2.3>.1-7].

Control Packets that require a Packet Identifier are listed in Table 2.5 - Control Packets that contain a Packet Identifier.

Table 2.5 - Control Packets that contain a Packet Identifier

Control Packet

Packet Identifier field

CONNECT

NO

CONNACK

NO

PUBLISH

YES (If QoS > 0)

PUBACK

YES

PUBREC

YES

PUBREL

YES

PUBCOMP

YES

SUBSCRIBE

YES

SUBACK

YES

UNSUBSCRIBE

YES

UNSUBACK

YES

PINGREQ

NO

PINGRESP

NO

DISCONNECT

NO

The Client and Server assign Packet Identifiers independently of each other. As a result, Client Server pairs can participate in concurrent message exchanges using the same Packet Identifiers.

Non normative comment

It is possible for a Client to send a PUBLISH Packet with Packet Identifier 0x1234 and then receive a different PUBLISH with Packet Identifier 0x1234 from its Server before it receives a PUBACK for the PUBLISH that it sent.

   Client                     Server

   PUBLISH Packet Identifier=0x1234---à

   ß--PUBLISH Packet Identifier=0x1234

   PUBACK Packet Identifier=0x1234---à

   ß--PUBACK Packet Identifier=0x1234

2.4 Payload

Table 2.6 - Control Packets that contain a Payload

Some MQTT Control Packets contain a payload as the final part of the packet, as described in Chapter 3 MQTT Control Packets. In the case of the PUBLISH packet this is the Application Message. Table 2.6 - Control Packets that contain a Payload lists the Control Packets that require a Payload.

Table 2.6 - Control Packets that contain a Payload

Control Packet

Payload

CONNECT

Required

CONNACK

None

PUBLISH

Optional

PUBACK

None

PUBREC

None

PUBREL

None

PUBCOMP

None

SUBSCRIBE

Required

SUBACK

Required

UNSUBSCRIBE

Required

UNSUBACK

None

PINGREQ

None

PINGRESP

None

DISCONNECT

None